
{***********************************************************}
{                                                           }
{      Informix esql "decimal.h"                            }
{                                                           }
{      Translated to Object Pascal by                       }
{      Copyright (c) 2001-2008 Luxena Software Company      }
{      http://www.luxena.com                                }
{      e-mail: support@luxena.com                           }
{                                                           }
{***********************************************************}

unit IfxDecimal;

{$I lx.inc}

{$IFDEF VER140_OR_ABOVE}
  {$ALIGN 8}
{$ENDIF}

interface

uses
  IfxTypes;
  

const

  // Unpacked Format (format for program usage)
  //
  //     Signed exponent "dec_exp" ranging from  -64 to +63
  //     Separate sign of mantissa "dec_pos"
  //     Base 100 digits (range 0 - 99) with decimal point
  //     immediately to the left of first digit.


  DECSIZE = 16;


  //  A decimal null will be represented internally by setting dec_pos
  //  equal to DECPOSNULL

  DECPOSNULL = -1;
  DECUNKNOWN = -2;


type

  PDecimal = ^TDecimal;
  TDecimal = record
    dec_exp: int2; // exponent base 100
    dec_pos: int2; // sign: 1=pos, 0=neg, -1=null
    dec_ndgts: int2; // number of significant digits
    dec_dgts: array[0..DECSIZE - 1] of Char; // actual digits base 100
  end;

{$IFDEF OSF_MLS}
  TIx_dec = TDecimal;
{$ELSE}
  TDec = TDecimal;
{$ENDIF}
  PDec = ^TDecimal;


  // Datatypes for DataBlade developers
  mi_money = TDecimal;
  mi_decimal = TDecimal;



  // DECLEN calculates minumum number of bytes
  // necessary to hold a decimal(m,n)
  // where m = total # significant digits and
  //	 n = significant digits to right of decimal

// #define DECLEN(m,n)	(((m)+((n)&1)+3)/2)
function DECLEN(m, n: Integer): Integer;

// #define DECLENGTH(len)	DECLEN(PRECTOT(len),PRECDEC(len))
function DECLENGTH(len: Integer): Integer;

// DECPREC calculates a default precision given
// number of bytes used to store number

// #define DECPREC(size)	(((size-1)<<9)+2)
function DECPREC(size: Integer): Integer;


// macros to look at and make encoded decimal precision
//
//  PRECTOT(x)		return total precision (digits total)
//  PRECDEC(x) 		return decimal precision (digits to right)
//  PRECMAKE(x,y)	make precision from total and decimal

// #define PRECTOT(x)	(((x)>>8) & 0xff)
function PRECTOT(x: Integer): Integer;

// #define PRECDEC(x)	((x) & 0xff)
function PRECDEC(x: Integer): Integer;

// #define PRECMAKE(x,y)	(((x)<<8) + (y))
function PRECMAKE(x, y: Integer): Integer;



// Packed Format  (format in records in files)
//
//    First byte =
//	  top 1 bit = sign 0=neg, 1=pos
//	  low 7 bits = Exponent in excess 64 format
//    Rest of bytes = base 100 digits in 100 complement format
//    Notes --	This format sorts numerically with just a
//		simple byte by byte unsigned comparison.
//		Zero is represented as 80,00,00,... (hex).
//		Negative numbers have the exponent complemented
//		and the base 100 digits in 100's complement



implementation


function DECLEN(m, n: Integer): Integer;
begin
  // #define DECLEN(m,n)	(((m)+((n)&1)+3)/2)
  Result := ((m + (n and 1) + 3) div 2);
end;

function DECLENGTH(len: Integer): Integer;
begin
  // #define DECLENGTH(len)	DECLEN(PRECTOT(len),PRECDEC(len))
  Result := DECLEN(PRECTOT(len), PRECDEC(len));
end;

function DECPREC(size: Integer): Integer;
begin
  // #define DECPREC(size)	(((size-1)<<9)+2)
  Result := (((size - 1) shl 9) + 2);
end;

function PRECTOT(x: Integer): Integer;
begin
  // #define PRECTOT(x)	(((x)>>8) & 0xff)
  Result := ((x shr 8) and $FF);
end;

function PRECDEC(x: Integer): Integer;
begin
  // #define PRECDEC(x)	((x) & 0xff)
  Result := (x and $FF);
end;

function PRECMAKE(x, y: Integer): Integer;
begin
  // #define PRECMAKE(x,y)	(((x)<<8) + (y))
  Result := ((x shl 8) + y);
end;

end.